from django.db import models
from django.contrib.auth.models import User
from django.core.validators import RegexValidator
import json


class AnsibleConfig(models.Model):
    """Ansible配置实例"""
    name = models.CharField(max_length=100, unique=True, verbose_name="配置名称")
    description = models.TextField(blank=True, verbose_name="描述")

    # 连接配置
    host = models.CharField(max_length=255, default='localhost', verbose_name="主机地址")
    port = models.IntegerField(default=22, verbose_name="SSH端口")
    username = models.CharField(max_length=100, verbose_name="用户名")

    # 认证方式
    AUTH_TYPES = [
        ('password', '密码认证'),
        ('key', '密钥认证'),
    ]
    auth_type = models.CharField(max_length=20, choices=AUTH_TYPES, default='password', verbose_name="认证方式")
    password = models.CharField(max_length=255, blank=True, verbose_name="密码")
    private_key = models.TextField(blank=True, verbose_name="私钥内容")

    # Ansible配置路径
    ansible_config_path = models.CharField(max_length=500, default='/etc/ansible/ansible.cfg', verbose_name="Ansible配置文件路径")
    inventory_path = models.CharField(max_length=500, default='/etc/ansible/hosts', verbose_name="Inventory文件路径")

    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    is_default = models.BooleanField(default=False, verbose_name="是否为默认配置")

    # 健康检查
    last_check_time = models.DateTimeField(null=True, blank=True, verbose_name="最后检查时间")
    health_status = models.CharField(max_length=20, default='unknown', verbose_name="健康状态")
    health_message = models.TextField(blank=True, verbose_name="健康检查消息")

    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="创建者")

    class Meta:
        verbose_name = "Ansible配置"
        verbose_name_plural = "Ansible配置"
        ordering = ['-created_at']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        # 确保只有一个默认配置
        if self.is_default:
            AnsibleConfig.objects.filter(is_default=True).update(is_default=False)
        super().save(*args, **kwargs)


class AnsibleInventory(models.Model):
    """Ansible Inventory管理"""
    config = models.ForeignKey(AnsibleConfig, on_delete=models.CASCADE, verbose_name="所属配置")
    name = models.CharField(max_length=100, verbose_name="Inventory名称")
    content = models.TextField(verbose_name="Inventory内容")
    file_path = models.CharField(max_length=500, verbose_name="文件路径")

    # 环境标识
    ENVIRONMENT_CHOICES = [
        ('dev', '开发环境'),
        ('test', '测试环境'),
        ('staging', '预发布环境'),
        ('prod', '生产环境'),
        ('manual', '手动创建'),
    ]
    environment = models.CharField(max_length=20, choices=ENVIRONMENT_CHOICES, default='manual', verbose_name="环境")

    # 解析后的结构化数据
    parsed_data = models.JSONField(default=dict, verbose_name="解析数据")

    # 统计信息
    hosts_count = models.IntegerField(default=0, verbose_name="主机数量")
    groups_count = models.IntegerField(default=0, verbose_name="组数量")

    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    last_sync_time = models.DateTimeField(null=True, blank=True, verbose_name="最后同步时间")

    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "Ansible Inventory"
        verbose_name_plural = "Ansible Inventory"
        unique_together = ['config', 'name']

    def __str__(self):
        return f"{self.config.name} - {self.name}"


class AnsibleCredential(models.Model):
    """Ansible凭据管理"""
    name = models.CharField(max_length=100, unique=True, verbose_name="凭据名称")
    description = models.TextField(blank=True, verbose_name="描述")

    # 凭据类型
    CREDENTIAL_TYPES = [
        ('ssh_key', 'SSH密钥'),
        ('password', '用户名密码'),
        ('aws_key', 'AWS访问密钥'),
        ('vault', 'Ansible Vault'),
    ]
    credential_type = models.CharField(max_length=20, choices=CREDENTIAL_TYPES, verbose_name="凭据类型")

    # 凭据内容（加密存储）
    username = models.CharField(max_length=100, blank=True, verbose_name="用户名")
    password = models.CharField(max_length=255, blank=True, verbose_name="密码")
    private_key = models.TextField(blank=True, verbose_name="私钥内容")
    public_key = models.TextField(blank=True, verbose_name="公钥内容")

    # AWS凭据
    access_key_id = models.CharField(max_length=100, blank=True, verbose_name="AWS Access Key ID")
    secret_access_key = models.CharField(max_length=255, blank=True, verbose_name="AWS Secret Access Key")

    # Vault密码
    vault_password = models.CharField(max_length=255, blank=True, verbose_name="Vault密码")

    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    last_used = models.DateTimeField(null=True, blank=True, verbose_name="最后使用时间")

    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="创建者")

    class Meta:
        verbose_name = "Ansible凭据"
        verbose_name_plural = "Ansible凭据"

    def __str__(self):
        return self.name


class AnsiblePlaybook(models.Model):
    """Ansible Playbook管理"""
    name = models.CharField(max_length=100, verbose_name="Playbook名称")
    description = models.TextField(blank=True, verbose_name="描述")

    # Playbook内容
    content = models.TextField(verbose_name="Playbook内容")
    file_path = models.CharField(max_length=500, blank=True, verbose_name="文件路径")

    # 关联配置
    config = models.ForeignKey(AnsibleConfig, on_delete=models.CASCADE, verbose_name="所属配置")

    # 标签和变量
    tags = models.CharField(max_length=500, blank=True, verbose_name="标签")
    variables = models.JSONField(default=dict, verbose_name="变量")

    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")

    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="创建者")

    class Meta:
        verbose_name = "Ansible Playbook"
        verbose_name_plural = "Ansible Playbook"
        unique_together = ['config', 'name']

    def __str__(self):
        return f"{self.config.name} - {self.name}"


class AnsibleJob(models.Model):
    """Ansible任务执行记录"""
    JOB_TYPES = [
        ('adhoc', 'Ad-hoc命令'),
        ('playbook', 'Playbook执行'),
    ]

    STATUS_CHOICES = [
        ('pending', '等待中'),
        ('running', '运行中'),
        ('success', '成功'),
        ('failed', '失败'),
        ('cancelled', '已取消'),
    ]

    # 基本信息
    name = models.CharField(max_length=200, verbose_name="任务名称")
    job_type = models.CharField(max_length=20, choices=JOB_TYPES, verbose_name="任务类型")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name="状态")

    # 关联对象
    config = models.ForeignKey(AnsibleConfig, on_delete=models.CASCADE, verbose_name="使用的配置")
    playbook = models.ForeignKey(AnsiblePlaybook, null=True, blank=True, on_delete=models.CASCADE, verbose_name="关联Playbook")
    credential = models.ForeignKey(AnsibleCredential, null=True, blank=True, on_delete=models.CASCADE, verbose_name="使用的凭据")

    # 执行参数
    inventory = models.CharField(max_length=500, verbose_name="目标清单")
    module_name = models.CharField(max_length=100, blank=True, verbose_name="模块名称")
    module_args = models.TextField(blank=True, verbose_name="模块参数")
    extra_vars = models.JSONField(default=dict, verbose_name="额外变量")
    tags = models.CharField(max_length=500, blank=True, verbose_name="标签")
    limit = models.CharField(max_length=500, blank=True, verbose_name="限制主机")

    # 执行结果
    result = models.JSONField(default=dict, verbose_name="执行结果")
    stdout = models.TextField(blank=True, verbose_name="标准输出")
    stderr = models.TextField(blank=True, verbose_name="错误输出")

    # 时间统计
    start_time = models.DateTimeField(null=True, blank=True, verbose_name="开始时间")
    end_time = models.DateTimeField(null=True, blank=True, verbose_name="结束时间")
    duration = models.IntegerField(default=0, verbose_name="执行时长(秒)")

    # 创建信息
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="执行者")

    class Meta:
        verbose_name = "Ansible任务"
        verbose_name_plural = "Ansible任务"
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.name} ({self.get_status_display()})"


class AnsibleGlobalSetting(models.Model):
    """Ansible全局设置"""
    key = models.CharField(max_length=100, unique=True, verbose_name="设置键")
    value = models.TextField(verbose_name="设置值")
    description = models.TextField(blank=True, verbose_name="描述")

    # 设置类型
    SETTING_TYPES = [
        ('string', '字符串'),
        ('integer', '整数'),
        ('boolean', '布尔值'),
        ('json', 'JSON对象'),
    ]
    setting_type = models.CharField(max_length=20, choices=SETTING_TYPES, default='string', verbose_name="设置类型")

    # 是否可编辑
    is_editable = models.BooleanField(default=True, verbose_name="是否可编辑")

    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "Ansible全局设置"
        verbose_name_plural = "Ansible全局设置"

    def __str__(self):
        return self.key

    def get_typed_value(self):
        """根据类型返回正确的值"""
        if self.setting_type == 'integer':
            return int(self.value)
        elif self.setting_type == 'boolean':
            return self.value.lower() in ['true', '1', 'yes']
        elif self.setting_type == 'json':
            return json.loads(self.value)
        else:
            return self.value



